#ifndef _MCU_CFG_H
#define _MCU_CFG_H

/*========================== INCLUDES ================================*/

/*include for standart intXX_t and uintXX_t*/
#include "stdint.h"

/*========================== TYPEDEFS =================================*/

/*=========================== DEFINES =================================*/

/****************** PLL configuration defines ****************************/
/** System Clock status definitions */   
#define MCU_STATUS_PLL_OFF            0u   
#define MCU_STATUS_PLL_OK             1u
#define MCU_STATUS_PLL_SELECTED       2u
#define MCU_STATUS_XTAL_SELECTED      3u
#define MCU_STATUS_PLL_LOCK_ERROR     4u
#define MCU_STATUS_SCM_ERROR          5u

/* PRE-COMPILED CONFIGURATIONS*/
#define CNF_BUS_FREQ_KHZ 	48000u	/* The frequency for the bus in KHz*/
#define CNF_XTAL_FREQ_KHZ 	4000u	/* The frequency for the pll xtal in KHz*/ 

#define CNF_BUS_FREQ_MHZ 	CNF_BUS_FREQ_KHZ/1000u 	/* Bus Frequency in MHZ for some calculations*/
#define CNF_XTAL_FREQ_MHZ   CNF_XTAL_FREQ_KHZ/1000u	/* XTAL Frequency in MHZ for some calculations*/

#define CNF_MCU_PLL_SELECT
	/*other options*/
	/*#define CNF_MCU_XTAL_SELECT*/


/* Oscillator Configurations based on external Hardware*/
#define CNF_OSC_LOOP_CTRLD_PIERCE 
	/* Other options: */
	/* #define  CNF_OSC_FULL_SWING_PIERCE   */

#ifdef CNF_OSC_LOOP_CTRLD_PIERCE
    #define XTAL_FREQ_MIN_KHZ   4000u 
    #define XTAL_FREQ_MAX_KHZ   16000u 
#else
	#ifdef CNF_OSC_FULL_SWING_PIERCE
    	#define XTAL_FREQ_MIN_KHZ   2000u 
        #define XTAL_FREQ_MAX_KHZ   40000u
    #endif
#endif
#define BUS_FREQ_MIN_KHZ    8000u 
#define BUS_FREQ_MAX_KHZ    50000u

/* Validate XTAL frequency range */
#if (CNF_XTAL_FREQ_KHZ < XTAL_FREQ_MIN_KHZ)
    #error "XTAL frequency is below the minimum allowed frequency"
#endif    
#if (CNF_XTAL_FREQ_KHZ > XTAL_FREQ_MAX_KHZ)
    #error "XTAL frequency is above the maximum allowed frequency"
#endif       

/* Validate BUS_FREQ_KHZ range */
#if (CNF_BUS_FREQ_KHZ < BUS_FREQ_MIN_KHZ)
    #error "BUS_FREQ_KHZ is below the minimum allowed frequency"
#endif    
#if (CNF_BUS_FREQ_KHZ > BUS_FREQ_MAX_KHZ)
    #error "BUS_FREQ_KHZ is above the maximum allowed frequency"    
#endif 

/****************** System configuration defines ****************************/
     
/** Select POSTDIV value to obtain the lowest possible FVCO/F_REF ratio and stable VCO value */
#if (CNF_BUS_FREQ_MHZ*4 > 120)
    #define POSTDIV_VALUE   0u
#elif ((CNF_BUS_FREQ_MHZ*4 >= 32) & (CNF_BUS_FREQ_MHZ*4 <= 120))
    #define POSTDIV_VALUE   1u
#elif (CNF_BUS_FREQ_MHZ*4 <= 32)
    #define POSTDIV_VALUE   (64/(CNF_BUS_FREQ_MHZ*4))
#endif  

/*-- Macros ------------------------------------------------------------------*/

/** ~~~~~~~~~~~~~ System clock Equations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/** FVCO = 2 * XTAL_FREQ * (SYNR+1) / (REFDV+1)                     Equation 1  */
/** FPLL = FVC0 / (2 * POSTDIV) (If POSTDIV != 0)                   Equation 2  */
/** FPLL = FVC0                 (If POSTDIV == 0)                   Equation 2a */
/** FBUS = FPLL/2                                                   Equation 4  */
/** FREF = XTAL_FREQ /(REFDV+1)                                     Equation 5  */
/** FPLL = 2 * XTAL_FREQ * (SYNR+1) / ((REFDV+1)*(2 * POSTDIV))     Equation 6  */
/** FBUS = FVC0/2               (If POSTDIV == 0)                   Equation 6  */
/** FBUS = FVCO/(4 * POSTDIV)   (If POSTDIV != 0)                   Equation 6a */

/** Select REFDV factor to obtain the highest possible REFCLK frequency F_REF */
#define REFDV_FACTOR        (CNF_XTAL_FREQ_MHZ/4)
/* Define REFDV_VALUE */
#define REFDV_VALUE         (REFDV_FACTOR-1)

/** Define desired VCO frequency value */
#if (POSTDIV_VALUE == 0)
    #define VCO_FREQ        (CNF_BUS_FREQ_MHZ*2)
#else
    #define VCO_FREQ        (CNF_BUS_FREQ_MHZ*4*POSTDIV_VALUE)
#endif    

/** Configure VCO gain for optimal stability and lock time */
/** VCOFRQ = 0; 32MHz <= fVCO <= 48MHz  */
#if ((VCO_FREQ >= 32) & (VCO_FREQ <= 48))
    #define VCOFRQ_VALUE    0u                                            
/** VCOFRQ = 1; 48MHz <  fVCO <= 80MHz  */
#elif ((VCO_FREQ > 48) & (VCO_FREQ <= 80))
    #define VCOFRQ_VALUE    1u 
/** VCOFRQ = 3; 80MHz <  fVCO <= 120MHz */    
#elif ((VCO_FREQ > 80) & (VCO_FREQ <= 120))
    #define VCOFRQ_VALUE    3u 
#else 
/** Selected VCO frequency is out of range */
    #error  "VCO Frequency is out of Range"
#endif

/* Define REFDV value based on Equation 1 */
#define SYNR_FACTOR     (REFDV_FACTOR*VCO_FREQ)/(2*CNF_XTAL_FREQ_MHZ)
/* Define SYNR value */
#define SYNR_VALUE      (SYNR_FACTOR-1)

/* Define F_REF based on Equation 4 */
#define F_REF           (CNF_XTAL_FREQ_MHZ/(REFDV_VALUE+1))

/** Configure PLL filter for optimal stability and lock time */
/** REFFRQ = 0; 1MHz <= fREF <= 2MHz */
#if ((F_REF >= 1) & (F_REF <= 2))
    #define REFFRQ_VALUE    0u  
/** REFFRQ = 1; 2MHz <  fREF <= 6MHz */
#elif ((F_REF >  2) & (F_REF <= 6))
    #define REFFRQ_VALUE    1u 
/** REFFRQ = 2; 6MHz <  fREF <= 12MHz */
#elif ((F_REF >  6) & (F_REF <= 12))
    #define REFFRQ_VALUE    2u 
/** REFFRQ = 3; fREF > 12MHz */
#elif (F_REF >  12)
    #define REFFRQ_VALUE    3u
#else
/** Selected F_REF frequency is out of range */
    #error  "F_REF Frequency is out of Range"        
#endif

/** Define actual BUS_FREQ value to be programmed in PLL circuit */
#if (POSTDIV_VALUE == 0)
    #define MCU_STATUS_ACTUAL_BUS_FREQ         (uint32_t)(2*CNF_XTAL_FREQ_MHZ*(SYNR_SYNDIV+1))*1000000 / ((REFDV_REFDIV+1)*2)
    #define MCU_STATUS_ACTUAL_BUS_FREQ_KHZ     (2*CNF_XTAL_FREQ_MHZ*SYNR_FACTOR)*1000 / (REFDV_FACTOR*2)
#else
    #define MCU_STATUS_ACTUAL_BUS_FREQ         (uint32_t)(2*CNF_XTAL_FREQ_MHZ*(SYNR_SYNDIV+1))*1000000 / ((REFDV_REFDIV+1)*4*POSTDIV_POSTDIV)
    #define MCU_STATUS_ACTUAL_BUS_FREQ_KHZ     (2*CNF_XTAL_FREQ_MHZ*SYNR_FACTOR)*1000 / (REFDV_FACTOR*4*POSTDIV_VALUE)
#endif
#if (MCU_STATUS_ACTUAL_BUS_FREQ_KHZ != CNF_BUS_FREQ_KHZ)
    #error "Selected BUS Frequency can NOT be calculated automatically. Manually set PLL values"
#endif

/*========================== FUNCTIONS ================================*/


#endif /* _MCU_CFG_H */